(* tOUT is defined in context "MultilayerThinFilmModel`" 
This package file provides additional downvalues to tOUT for faster execution 
using specific pattern matching for special cases.*)
Options[OutputTransferC] = {DetectionSide -> First};

OutputTransferC[{Px_, Py_, Pz_}, Omega_, ThetaLIST_, nlist_, Dlist_, v_Integer, nbarINT_, opts:OptionsPattern[]] :=
	Block[{outSI, outPhi, outSII, inTout, c = 0,
		   DetectSide = OptionValue[DetectionSide]@{"0+","kp1-'"}},
		  
		(outPhi[v-#] = PhaseMv[Omega, ThetaLIST[[v+1-#]], nlist[[v+1-#]], Quiet @ Dlist[[v-#]]])& /@ {0, 1};

    	({outSI["v+",#],
     	 outSII["v+",#],
     	 outSI["v-'",#],
     	 outSII["v-'",#]} =
		 {AbelesSIv[#, Omega, ThetaLIST, nlist, Dlist, v - 1],
		  RefractionMv[#, Sequence @@ ThetaLIST[[v ;; v + 1]], Sequence @@ nlist[[v ;; v + 1]]] . outPhi[v] . outSII["v-'",#],
		  outSI["v+", #] . outPhi[v - 1] . RefractionMv[#, Sequence @@ ThetaLIST[[v ;; v + 1]], Sequence @@ nlist[[v ;; v + 1]]],
		  AbelesSIIv[#, Omega, ThetaLIST, nlist, Dlist, v]})& /@ {"s", "p"};
	
		(inTout[#] = 
			DiagonalMatrix[{ExternalTransferC[#, DetectSide, outSI[#, "p"], outPhi[v - c], outSII[#, "p"]],
							ExternalTransferC[#, DetectSide, outSI[#, "s"], outPhi[v - c++], outSII[#, "s"]], 0}])& /@ {"v-'", "v+"};
			
		(pj[Omega, ThetaLIST[[v]], nlist[[v]]] inTout["v+"] . FresnelL["v+", ThetaLIST[[v;;v+1]], nlist[[v;;v+1]], nbarINT] + 
     	 pj[Omega, ThetaLIST[[v + 1]], nlist[[v + 1]]] inTout["v-'"] . FresnelL["v-'", ThetaLIST[[v;;v+1]], nlist[[v;;v+1]], nbarINT]) . {Px, Py, Pz}]

OutputTransferC[{Px_, Py_, Pz_}, Omega_, ThetaPM0_, n0_,ND:{{_,_}..}, nkp1_, v_Integer, nbarINT_, opts:OptionsPattern[]]:=
Block[{ThetaLIST = RefractionAngle[ThetaPM0,n0,{n0}~Join~ND[[All,1]]~Join~{nkp1}]},
	OutputTransferC[{Px, Py, Pz}, Omega, ThetaLIST, {n0}~Join~ND[[All,1]]~Join~{nkp1}, ND[[All,2]], v, nbarINT, opts]]

OutputTransferC[{Px_, Py_, Pz_}, Omega_, ThetaND:{{_, _}, {_, _, _}.., {_, _}}, v_Integer, nbarINT_, opts:OptionsPattern[]]:=
	OutputTransferC[{Px, Py, Pz}, Omega, ThetaND[[All,1]], ThetaND[[All,2]], ThetaND[[2;;-2,2]], v, nbarINT, opts];

OutputTransferC[___]/;Message[General::badargs,OutputTransferC]:= "unevaluated"



OutputTransferC[{0, Py_, 0}, Omega_, ThetaLIST_, nlist_, Dlist_, v_Integer, nbarINT_] /; v == 1 :=
	(pj[Omega, ThetaLIST[[v]], nlist[[v]]] * (1 + rs[Sequence @@ ThetaLIST[[v ;; v + 1]], Sequence @@ nlist[[v;;v+1]]]) + 
     pj[Omega, ThetaLIST[[v + 1]], nlist[[v + 1]]] * ExternalTransferC["v-'", "0+", 
		   												  RefractionMv["s", Sequence @@ ThetaLIST[[v ;; v + 1]], Sequence @@ nlist[[v ;; v + 1]]], 
		 												  PhaseMv[Omega, ThetaLIST[[2]], nlist[[2]], Dlist[[1]]], 
														  AbelesSIIv["s", Omega, ThetaLIST, nlist, Dlist, v]] * 
		 (1 + rs[ThetaLIST[[v+1]], ThetaLIST[[v]], nlist[[v+1]], nlist[[v]]])) * {0, Py, 0}

OutputTransferC[{0, Py_, 0}, Omega_, ThetaLIST_, nlist_, Dlist_, v_Integer, nbarINT_] :=
	Block[{outSI, outPhi, outSII},
		  
		(outPhi[v-#] = PhaseMv[Omega, ThetaLIST[[v+1-#]], nlist[[v+1-#]], Quiet @ Dlist[[v-#]]])& /@ {0, 1};

    	({outSI["v+",#],
     	 outSII["v+",#],
     	 outSI["v-'",#],
     	 outSII["v-'",#]} =
		 {AbelesSIv[#, Omega, ThetaLIST, nlist, Dlist, v - 1],
		  RefractionMv[#, Sequence @@ ThetaLIST[[v ;; v + 1]], Sequence @@ nlist[[v ;; v + 1]]] . outPhi[v] . outSII["v-'",#],
		  outSI["v+", #] . outPhi[v - 1] . RefractionMv[#, Sequence @@ ThetaLIST[[v ;; v + 1]], Sequence @@ nlist[[v ;; v + 1]]],
		  AbelesSIIv[#, Omega, ThetaLIST, nlist, Dlist, v]})& /@ {"s"};
			
		( pj[Omega, ThetaLIST[[v]], nlist[[v]]] * ExternalTransferC["v+", "0+" ,outSI["v+", "s"], outPhi[v - 1], outSII["v+", "s"]] * 
		  (1 + rs[Sequence @@ ThetaLIST[[v ;; v + 1]], Sequence @@ nlist[[v;;v+1]]]) +
		  pj[Omega, ThetaLIST[[v + 1]], nlist[[v + 1]]] * ExternalTransferC["v-'", "0+", outSI["v-'", "s"],outPhi[v], outSII["v-'", "s"]] *
		  (1 + rs[ThetaLIST[[v+1]], ThetaLIST[[v]], nlist[[v+1]], nlist[[v]]])
		 ) * {0, Py, 0}]

OutputTransferC[{0, Py_, 0}, Omega_, ThetaLIST_, nlist_, Dlist_, v_Integer, nbarINT_] /; v == Length[Dlist] + 1 :=	
	( pj[Omega, ThetaLIST[[v]], nlist[[v]]] * ExternalTransferC["v+", "0+" ,
													 AbelesSIv["s", Omega, ThetaLIST, nlist, Dlist, v - 1], 
													 PhaseMv[Omega, ThetaLIST[[v]], nlist[[v]], Quiet @ Dlist[[v]]],
													 AbelesSIIv["s", Omega, ThetaLIST, nlist, Dlist, v - 1]] * 
		  (1 + rs[Sequence @@ ThetaLIST[[v ;; v + 1]], Sequence @@ nlist[[v;;v+1]]])) * {0, Py, 0};(*]) 
	) * {0, Py, 0};*)
	
(*******************************************************************************************************)
(*******************************************************************************************************)
(*******************************************************************************************************)
(*******************************************************************************************************)
(*Switch order of nbarINT and v args for convenience in GenerateInterfacialModel*)
(*OutputTransferC[{Px_, Py_, Pz_}, Omega_, ThetaLIST_, nlist_, Dlist_, nbarINT_, v_Integer, opts:OptionsPattern[]] :=
	Block[{outSI, outPhi, outSII, inTout, c = 0,
		   DetectSide = OptionValue[DetectionSide]@{"0+","kp1-'"}},
		  
		(outPhi[v-#] = PhaseMv[Omega, ThetaLIST[[v+1-#]], nlist[[v+1-#]], Quiet @ Dlist[[v-#]]])& /@ {0, 1};

    	({outSI["v+",#],
     	 outSII["v+",#],
     	 outSI["v-'",#],
     	 outSII["v-'",#]} =
		 {AbelesSIv[#, Omega, ThetaLIST, nlist, Dlist, v - 1],
		  RefractionMv[#, Sequence @@ ThetaLIST[[v ;; v + 1]], Sequence @@ nlist[[v ;; v + 1]]] . outPhi[v] . outSII["v-'",#],
		  outSI["v+", #] . outPhi[v - 1] . RefractionMv[#, Sequence @@ ThetaLIST[[v ;; v + 1]], Sequence @@ nlist[[v ;; v + 1]]],
		  AbelesSIIv[#, Omega, ThetaLIST, nlist, Dlist, v]})& /@ {"s", "p"};
	
		(inTout[#] = 
			DiagonalMatrix[{ExternalTransferC[#, DetectSide, outSI[#, "p"], outPhi[v - c], outSII[#, "p"]],
							ExternalTransferC[#, DetectSide, outSI[#, "s"], outPhi[v - c++], outSII[#, "s"]], 0}])& /@ {"v-'", "v+"};
			
		(pj[Omega, ThetaLIST[[v]], nlist[[v]]] inTout["v+"] . FresnelL["v+", ThetaLIST[[v;;v+1]], nlist[[v;;v+1]], nbarINT] + 
     	 pj[Omega, ThetaLIST[[v + 1]], nlist[[v + 1]]] inTout["v-'"] . FresnelL["v-'", ThetaLIST[[v;;v+1]], nlist[[v;;v+1]], nbarINT]) . {Px, Py, Pz}]

OutputTransferC[{Px_, Py_, Pz_}, Omega_, ThetaPM0_, n0_,ND:{{_,_}..}, nkp1_, nbarINT_, v_Integer, opts:OptionsPattern[]]:=
Block[{ThetaLIST = RefractionAngle[ThetaPM0,n0,{n0}~Join~ND[[All,1]]~Join~{nkp1}]},
	OutputTransferC[{Px, Py, Pz}, Omega, ThetaLIST, {n0}~Join~ND[[All,1]]~Join~{nkp1}, ND[[All,2]], v, nbarINT, opts]]

OutputTransferC[{Px_, Py_, Pz_}, Omega_, ThetaND:{{_, _}, {_, _, _}.. {_, _}}, nbarINT_, v_Integer, opts:OptionsPattern[]]:=
	OutputTransferC[{Px, Py, Pz}, Omega, ThetaND[[All,1]], ThetaND[[All,2]], ThetaND[[2;;-2,2]], v, nbarINT, opts];

OutputTransferC[___]/;Message[General::badargs,OutputTransferC]:= "unevaluated"



OutputTransferC[{0, Py_, 0}, Omega_, ThetaLIST_, nlist_, Dlist_, nbarINT_, v_Integer] /; v == 1 :=
	(pj[Omega, ThetaLIST[[v]], nlist[[v]]] * (1 + rs[Sequence @@ ThetaLIST[[v ;; v + 1]], Sequence @@ nlist[[v;;v+1]]]) + 
     pj[Omega, ThetaLIST[[v + 1]], nlist[[v + 1]]] * ExternalTransferC["v-'", "0+", 
		   												  RefractionMv["s", Sequence @@ ThetaLIST[[v ;; v + 1]], Sequence @@ nlist[[v ;; v + 1]]], 
		 												  PhaseMv[Omega, ThetaLIST[[2]], nlist[[2]], Dlist[[1]]], 
														  AbelesSIIv["s", Omega, ThetaLIST, nlist, Dlist, v]] * 
		 (1 + rs[ThetaLIST[[v+1]], ThetaLIST[[v]], nlist[[v+1]], nlist[[v]]])) * {0, Py, 0}

OutputTransferC[{0, Py_, 0}, Omega_, ThetaLIST_, nlist_, Dlist_, nbarINT_, v_Integer] :=
	Block[{outSI, outPhi, outSII},
		  
		(outPhi[v-#] = PhaseMv[Omega, ThetaLIST[[v+1-#]], nlist[[v+1-#]], Quiet @ Dlist[[v-#]]])& /@ {0, 1};

    	({outSI["v+",#],
     	 outSII["v+",#],
     	 outSI["v-'",#],
     	 outSII["v-'",#]} =
		 {AbelesSIv[#, Omega, ThetaLIST, nlist, Dlist, v - 1],
		  RefractionMv[#, Sequence @@ ThetaLIST[[v ;; v + 1]], Sequence @@ nlist[[v ;; v + 1]]] . outPhi[v] . outSII["v-'",#],
		  outSI["v+", #] . outPhi[v - 1] . RefractionMv[#, Sequence @@ ThetaLIST[[v ;; v + 1]], Sequence @@ nlist[[v ;; v + 1]]],
		  AbelesSIIv[#, Omega, ThetaLIST, nlist, Dlist, v]})& /@ {"s"};
			
		( pj[Omega, ThetaLIST[[v]], nlist[[v]]] * ExternalTransferC["v+", "0+" ,outSI["v+", "s"], outPhi[v - 1], outSII["v+", "s"]] * 
		  (1 + rs[Sequence @@ ThetaLIST[[v ;; v + 1]], Sequence @@ nlist[[v;;v+1]]]) +
		  pj[Omega, ThetaLIST[[v + 1]], nlist[[v + 1]]] * ExternalTransferC["v-'", "0+", outSI["v-'", "s"],outPhi[v], outSII["v-'", "s"]] *
		  (1 + rs[ThetaLIST[[v+1]], ThetaLIST[[v]], nlist[[v+1]], nlist[[v]]])
		 ) * {0, Py, 0}]

OutputTransferC[{0, Py_, 0}, Omega_, ThetaLIST_, nlist_, Dlist_, nbarINT_, v_Integer] /; v == Length[Dlist] + 1 :=	
	( pj[Omega, ThetaLIST[[v]], nlist[[v]]] * ExternalTransferC["v+", "0+" ,
													 AbelesSIv["s", Omega, ThetaLIST, nlist, Dlist, v - 1], 
													 PhaseMv[Omega, ThetaLIST[[v]], nlist[[v]], Quiet @ Dlist[[v]]],
													 AbelesSIIv["s", Omega, ThetaLIST, nlist, Dlist, v - 1]] * 
		  (1 + rs[Sequence @@ ThetaLIST[[v ;; v + 1]], Sequence @@ nlist[[v;;v+1]]])) * {0, Py, 0};(*]) 
	) * {0, Py, 0};*)
*)